package com.icinfo.cloud.provider.common.utils;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.xml.bind.DatatypeConverter;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

import cn.hutool.core.util.ObjectUtil;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.framework.mybatis.mapper.util.StringUtil;
import gui.ava.html.image.generator.HtmlImageGenerator;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;


import java.io.*;
import java.net.URL;


/**
 * 描述：图片转换工具类
 *
 * @author shishengyao
 * @date 2022/7/21
 */
public class ImageUtil {

    /**
     * dpi越大转换后越清晰，相对转换速度越慢
     */
    private static final Integer DPI = 100;

    /**
     * 转换后的图片类型
     */
    private static final String IMG_TYPE = "png";

    /**
     * 描述：使用图片变灰色
     *
     * @param imgBase64Str img base64 str
     * @return {@link String }
     * @author shishengyao
     * @date 2022/08/09
     */
    public static String binaryImage(String imgBase64Str) {
        if (imgBase64Str.lastIndexOf(Constant.STRING_COMMA) > -1) {
            imgBase64Str = imgBase64Str.substring(imgBase64Str.lastIndexOf(Constant.STRING_COMMA) + 1);
        }
        BufferedImage originalImage = null;
        byte[] bytes = DatatypeConverter.parseBase64Binary(imgBase64Str);
        InputStream inputStream = new ByteArrayInputStream(bytes);
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            originalImage = ImageIO.read(inputStream);
            BufferedImage grayImage;
            int imageWidth = originalImage.getWidth();
            int imageHeight = originalImage.getHeight();

            grayImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
            ColorConvertOp cco = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
            cco.filter(originalImage, grayImage);
            // 设置图片的格式
            ImageIO.write(grayImage, "png", outputStream);
            bytes = Base64.encodeBase64(outputStream.toByteArray());
            String base64 = new String(bytes);
            inputStream.close();
            outputStream.close();
            return "data:image/png;base64," + base64;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    /**
     * 描述：将图片制成灰色
     *
     * @param imgBase64Str img base64 str
     * @return {@link String }
     * @author shishengyao
     * @date 2022/07/21
     */
    public static String binaryImage2(String imgBase64Str) {
        if (imgBase64Str.lastIndexOf(Constant.STRING_COMMA) > -1) {
            imgBase64Str = imgBase64Str.substring(imgBase64Str.lastIndexOf(Constant.STRING_COMMA) + 1);
        }
        BufferedImage originalImage;
        byte[] bytes = DatatypeConverter.parseBase64Binary(imgBase64Str);
        InputStream inputStream = new ByteArrayInputStream(bytes);
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            originalImage = ImageIO.read(inputStream);
            BufferedImage grayPicture;
            //图片缓冲流
            //   BufferedImage originalImage = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_BYTE_BINARY);

            int oldHeight = originalImage.getHeight();
            int oldWidth = originalImage.getWidth();
            int destWidth = oldWidth * 2;
            int destHeight = oldHeight * 2;

            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
            ColorConvertOp op = new ColorConvertOp(cs, null);
            originalImage = op.filter(originalImage, null);
            //图片缓冲流
            BufferedImage outImage = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = (Graphics2D) outImage.getGraphics();
            // 设置背景颜色
            graphics2D.setBackground(Color.WHITE);
            graphics2D.clearRect(0, 0, destWidth, destHeight);
            // 设置图片居中显示
            graphics2D.drawImage(originalImage, (destWidth - oldWidth) / 2, (destHeight - oldHeight) / 2, null);

            // 设置图片的格式
            ImageIO.write(outImage, IMG_TYPE, outputStream);
            bytes = Base64.encodeBase64(outputStream.toByteArray());
            String base64 = new String(bytes);
            inputStream.close();
            outputStream.close();
            return "data:image/png;base64," + base64;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 描述：将图片制成灰色
     *
     * @param imgBase64Str img base64 str
     * @return {@link String }
     * @author shishengyao
     * @date 2022/07/21
     */
    public static String binaryImageWhite(String imgBase64Str) {
        if (imgBase64Str.lastIndexOf(Constant.STRING_COMMA) > -1) {
            imgBase64Str = imgBase64Str.substring(imgBase64Str.lastIndexOf(Constant.STRING_COMMA) + 1);
        }
        BufferedImage originalImage;
        byte[] bytes = DatatypeConverter.parseBase64Binary(imgBase64Str);
        InputStream inputStream = new ByteArrayInputStream(bytes);
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            originalImage = ImageIO.read(inputStream);
            int oldHeight = originalImage.getHeight();
            int oldWidth = originalImage.getWidth();
            int destWidth = oldWidth * 2;
            int destHeight = oldHeight * 2;
            //图片缓冲流
            //  BufferedImage outImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
            BufferedImage outImage = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = (Graphics2D) outImage.getGraphics();
            // 设置背景颜色
            graphics2D.setBackground(Color.WHITE);
            graphics2D.clearRect(0, 0, destWidth, destHeight);

            // 设置图片居中显示
            graphics2D.drawImage(originalImage, (destWidth - oldWidth) / 2, (destHeight - oldHeight) / 2, null);
            // 设置图片的格式
            ImageIO.write(outImage, IMG_TYPE, outputStream);
            bytes = Base64.encodeBase64(outputStream.toByteArray());
            String base64 = new String(bytes);
            inputStream.close();
            outputStream.close();
            return "data:image/png;base64," + base64;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    /**
     * 描述：处理图片为灰色并使背景透明
     *
     * @param imgBase64Str img base64 str
     * @return {@link String }
     * @author shishengyao
     * @date 2022/08/09
     */
    public static String getGrayImage(String imgBase64Str) {
        if (imgBase64Str.lastIndexOf(Constant.STRING_COMMA) > -1) {
            imgBase64Str = imgBase64Str.substring(imgBase64Str.lastIndexOf(Constant.STRING_COMMA) + 1);
        }
        BufferedImage bi;
        byte[] bytes = DatatypeConverter.parseBase64Binary(imgBase64Str);
        InputStream inputStream = new ByteArrayInputStream(bytes);
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            bi = ImageIO.read(inputStream);

            //图片缓冲流
            BufferedImage bufferedImage = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
            for (int i = 0; i < bi.getWidth(); i++) {
                for (int j = 0; j < bi.getHeight(); j++) {
                    int rgb = bi.getRGB(i, j);
                    bufferedImage.setRGB(i, j, rgb);
                }
            }
            Image image = (Image) bufferedImage;
            //将原图片的二进制转化为ImageIcon
            ImageIcon imageIcon = new ImageIcon(image);
            bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),
                    BufferedImage.TYPE_4BYTE_ABGR);
            int width = imageIcon.getIconWidth();
            int height = imageIcon.getIconHeight();
            Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics();
            graphics2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
            int alpha = 255;

            //这个背景底色的选择，我这里选择的是比较偏的位置，可以修改位置。背景色选择不知道有没有别的更优的方式（比如先过滤一遍获取颜色次数最多的，但是因为感觉做起来会比较复杂没去实现），如果有可以评论。
            int RGB = bufferedImage.getRGB(width - 1, height - 1);

            for (int i = bufferedImage.getMinX(); i < width; i++) {
                for (int j = bufferedImage.getMinY(); j < height; j++) {

                    int rgb = bufferedImage.getRGB(i, j);

                    int r = (rgb & 0xff0000) >> 16;
                    int g = (rgb & 0xff00) >> 8;
                    int b = (rgb & 0xff);
                    int R = (RGB & 0xff0000) >> 16;
                    int G = (RGB & 0xff00) >> 8;
                    int B = (RGB & 0xff);
                    //a为色差范围值，渐变色边缘处理，数值需要具体测试，50左右的效果比较可以
                    int a = 45;
                    if (Math.abs(R - r) < a && Math.abs(G - g) < a && Math.abs(B - b) < a) {
                        alpha = 0;
                    } else {
                        alpha = 255;
                    }
                    rgb = (alpha << 24) | (rgb & 0x00ffffff);
                    bufferedImage.setRGB(i, j, rgb);
                }
            }
            // 设置图片的格式
            ImageIO.write(bufferedImage, IMG_TYPE, outputStream);
            bytes = Base64.encodeBase64(outputStream.toByteArray());
            String base64 = new String(bytes);
            inputStream.close();
            outputStream.close();
            return "data:image/png;base64," + base64;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    /**
     * 描述：缩放图片
     *
     * @param bufferedImage 缓冲图像
     * @param scale         规模
     * @return {@link BufferedImage }
     * @author shishengyao
     * @date 2022/08/16
     */
    public static BufferedImage zoomPic(BufferedImage bufferedImage, String scale) throws IOException {
        // 3、获取图片的原始宽高
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        // 4、获取图片的缩放【宽高都是*了缩放比例的再取整】
        Image scaledInstance = bufferedImage.getScaledInstance(Double.valueOf(width * 0.25).intValue(), Double.valueOf(height * .25).intValue(), Image.SCALE_DEFAULT);
        // 5、将Image类型转换成BufferedImage对象[BufferedImage.TYPE_INT_ARGB：表示具有8位RGBA颜色成分的整数像素的图像]
        BufferedImage newImage = new BufferedImage(Double.valueOf(width * 0.25).intValue(), Double.valueOf(height * 0.25).intValue(), BufferedImage.TYPE_INT_ARGB);
        // 一个新的图形上下文，这是这个图形上下文的副本
        Graphics g = newImage.getGraphics();
        // 绘制图片大小
        boolean b = g.drawImage(scaledInstance, 0, 0, null);
        // 释放文件资源
        g.dispose();
        return newImage;
    }

    /**
     * 待合并的两张图必须满足这样的前提，如果水平方向合并，则高度必须相等；如果是垂直方向合并，宽度必须相等。
     * mergeImage方法不做判断，自己判断。
     *
     * @param imgBase64Str1 待合并的第一张图
     * @param imgBase64Str2 带合并的第二张图
     * @return 返回合并后的BufferedImage对象
     * @throws IOException
     */
    public static String mergeImage(String imgBase64Str1, String imgBase64Str2) {
        if (StringUtil.isEmpty(imgBase64Str1)) {
            return imgBase64Str2;
        }
        if (StringUtil.isEmpty(imgBase64Str2)) {
            return imgBase64Str1;
        }
        BufferedImage img1 = base64TransBufferedImage(imgBase64Str1);
        BufferedImage img2 = base64TransBufferedImage(imgBase64Str2);
        String mergeImage = "";
        try {
            int w1 = img1.getWidth();
            int h1 = img1.getHeight();
            int w2 = img2.getWidth();
            int h2 = img2.getHeight();
            // 从图片中读取RGB
            int[] ImageArrayOne = new int[w1 * h1];
            // 逐行扫描图像中各个像素的RGB到数组中
            ImageArrayOne = img1.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1);
            int[] ImageArrayTwo = new int[w2 * h2];
            ImageArrayTwo = img2.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);
            // 生成新图片
            BufferedImage destImage = null;
            destImage = new BufferedImage(w1, h1, BufferedImage.TYPE_INT_RGB);
            // 设置上半部分或左半部分的RGB
            destImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1);
            // 加载水印图片文件
            Graphics2D resizedG = destImage.createGraphics();
            resizedG.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, (float) 1));
            resizedG.drawImage(img2, w1 / 2 - w2 / 2, h1 / 2 - h2 / 2, null);
            resizedG = destImage.createGraphics();
            resizedG.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f));


            resizedG.dispose();

            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            ImageIO.write(destImage, "png", stream);
            byte[] bytes = Base64.encodeBase64(stream.toByteArray());
            stream.flush();
            stream.close();
            mergeImage = new String(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "data:image/png;base64," + mergeImage;
    }

    private static BufferedImage base64TransBufferedImage(String imgBase64Str) {
        if (imgBase64Str.lastIndexOf(Constant.STRING_COMMA) > -1) {
            imgBase64Str = imgBase64Str.substring(imgBase64Str.lastIndexOf(Constant.STRING_COMMA) + 1);
        }
        BufferedImage bufferedImage = null;
        try {
            byte[] bytes = DatatypeConverter.parseBase64Binary(imgBase64Str);
            InputStream inputStream = new ByteArrayInputStream(bytes);
            bufferedImage = ImageIO.read(inputStream);
            inputStream.close();
        } catch (IOException e) {
            throw new BusinessException("签字捺印失败");
        } finally {

        }
        return bufferedImage;
    }


    /**
     * 图像url转换base64
     *
     * @return {@link String }
     * @author shishengyao
     * @date 2023/02/09
     */
    public static String imageUrlTransBase64(String imageUrl) throws IOException {
        if (StringUtil.isEmpty(imageUrl)) {
            return "";
        }
        String imageBase64Str = "";
        InputStream inputStream = null;
        try {
            URL url = new URL(imageUrl);
            inputStream = url.openStream();
            byte[] fileContent = IOUtils.toByteArray(inputStream);
            String base64Str = java.util.Base64.getEncoder().encodeToString(fileContent);
            if (null != base64Str && base64Str != "") {
                imageBase64Str = "data:image/png;base64," + base64Str;
            } else {
                imageBase64Str = imageUrl;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            inputStream.close();
        }
        return imageBase64Str;


    }

    /**
     * 描述：将两张图片叠合（保持背景透明）
     *
     * @param backgroundImg 背景图片base64
     * @param upperImg      上面的图片base64
     * @return {@link String }
     * @author shishengyao
     * @date 2022/08/16
     */
    public static String overlapImage(String backgroundImg, String upperImg) {
        if (ObjectUtil.isEmpty(backgroundImg)) {
            return upperImg;
        }
        if (ObjectUtil.isEmpty(upperImg)) {
            return backgroundImg;
        }
        try {
            BufferedImage backBufferedImage = base64TransBufferedImage(backgroundImg);
            BufferedImage upperBufferedImage = base64TransBufferedImage(upperImg);
            // 输出图片宽度
            int width = backBufferedImage.getWidth();
            // 输出图片高度
            int height = backBufferedImage.getHeight();
            // 上层图片宽度
            int upperWidth = upperBufferedImage.getWidth();
            // 上层图片高度
            int upperHeight = upperBufferedImage.getHeight();
            BufferedImage descBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D graphics2d = (Graphics2D) descBufferedImage.getGraphics();
            //设置背景图为白色
            graphics2d.setBackground(Color.WHITE);
            graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            // 往画布上添加图片,并设置边距
            graphics2d.drawImage(backBufferedImage, null, 0, 0);
            graphics2d.drawImage(upperBufferedImage, width / 2 - upperWidth / 2, height / 2 - upperHeight / 2, null);
            graphics2d.dispose();

            //输出图片
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            ImageIO.write(descBufferedImage, "png", stream);
            byte[] bytes = Base64.encodeBase64(stream.toByteArray());
            stream.flush();
            stream.close();
            String mergeImage = new String(bytes);
            return "data:image/png;base64," + mergeImage;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("签字捺印失败");
        }

    }

    public static BufferedImage getGrayPicture(BufferedImage originalImage) {
        BufferedImage grayPicture;
        int imageWidth = originalImage.getWidth();
        int imageHeight = originalImage.getHeight();

        grayPicture = new BufferedImage(imageWidth, imageHeight,
                BufferedImage.TYPE_INT_RGB);
        ColorConvertOp cco = new ColorConvertOp(ColorSpace
                .getInstance(ColorSpace.CS_GRAY), null);
        cco.filter(originalImage, grayPicture);
        return grayPicture;

    }
}
